﻿using SuperX.Common.Collection;
using SuperX.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SuperX.Common.Log;
using System.Threading;
using SqlSugar;

namespace SuperX.MiddlewareBase
{
    public abstract class ManagerBase : BasicObjCollection<IBasicObject>
    {
        public Action ProcessingTagValue;

        public ManagerBase()
        {
            FailMsgList = new List<DataCache>();
        }

        /// <summary>
        /// 发送失败的数据集合
        /// </summary>
        public List<DataCache> FailMsgList { get; set; }

        /// <summary>
        /// 缓存数据库
        /// </summary>
        public SqlSugarClient Db { get; set; }

        /// <summary>
        /// 控制是否启动线程
        /// </summary>
        private bool _IsStart { get; set; } = false;

        /// <summary>
        /// 消息发送线程
        /// </summary>
        private Thread SendThread;

        private ObjectCollection<ManagerBase, ServerBase> _hosts;

        public ObjectCollection<ManagerBase, ServerBase> Hosts
        {
            get { return _hosts ?? (_hosts = new ObjectCollection<ManagerBase, ServerBase>(this)); }
            set
            {
                _hosts = value;
                _hosts.SetParent(this);
            }
        }

        public virtual void Init()
        {
            try
            {
                _IsStart = true;
                //后台线程负责发送数据
                SendThread = new Thread(SendData) { IsBackground = true };
            }
            catch (Exception ex)
            {
                Logger.ErrorException(ex);
            }
        }

        public virtual void Start()
        {
            SendThread?.Start();
        }

        public virtual void Stop()
        {
            foreach (var Host in Hosts)
            {
                Host.Stop();
            }
            _IsStart = false;
            SendThread?.Abort();
        }

        public virtual void SendData()
        {
            while (_IsStart)
            {
                try
                {
                    FailMsgList.Clear();
                    CheckChannel();
                    AddToDb(FailMsgList);//统一入库
                }
                catch (Exception ex)
                {
                    Logger.ErrorException(ex);
                }
                finally
                {
                    Thread.Sleep(50);
                }
            }
        }

        public virtual void CheckChannel()
        {
            ProcessingTagValue?.Invoke();
        }

        /// <summary>
        /// 将消息缓存进数据库
        /// </summary>
        /// <param name="TagItems"></param>
        public void AddToDb(List<DataCache> tagItems)
        {
            if (tagItems.Count > 0) Db.Insertable(tagItems).ExecuteCommand();
        }

        /// <summary>
        /// 获取该通道的缓存数据
        /// </summary>
        /// <param name="queueName"></param>
        /// <returns></returns>
        public List<DataCache> GetCacheData(string queueName)
        {
            var data = new List<DataCache>();
            try
            {
                data = Db.Queryable<DataCache>()
                    .Where(r => r.QueueName == queueName)
                    .OrderBy(r => new { r.ChangedTime, r.Id })
                    .ToList();
            }
            catch (Exception ex)
            {
                var funame = FullName;
                Logger.ErrorException(ex);
            }
            return data;
        }

        public override IBasicObject this[string name] => Hosts[name];

        public override List<string> GetKeys()
        {
            return Hosts.Keys.ToList();
        }

        public override List<IBasicObject> GetValues()
        {
            var group = Hosts.Values.OfType<IBasicObject>().ToList();
            return group;
        }

        public override bool IsUniqueName(string name, IObjCollection parent)
        {
            if (parent != null)
            {
                return parent.IsUniqueName(name, null);
            }
            return Hosts[name] == null;
        }
    }
}